package com.lib.krismile.ui.web;

import android.annotation.TargetApi;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebResourceResponse;
import android.webkit.WebSettings;
import android.webkit.WebView;

import androidx.lifecycle.ViewModelProvider;

import com.blankj.utilcode.util.StringUtils;
import com.github.lzyzsd.jsbridge.DefaultHandler;
import com.lib.krismile.R;
import com.lib.krismile.base.BaseActivity;
import com.lib.krismile.databinding.ActivitySingleWebBinding;
import com.lib.krismile.util.NetworkUtils;

/*
 * @author ： wangJiaWei
 * @date : 2021/3/29
 * @description ：
 */
public class SingleWebActivity extends BaseActivity<ActivitySingleWebBinding, SingleWebViewModel> {

    //加载失败的页面
    private final String errorPage = "file:///android_asset/error_page.html";


    @Override
    protected int getLayoutResId() {
        return R.layout.activity_single_web;
    }

    @Override
    protected void initViewModel() {
        mViewModel = new ViewModelProvider(this).get(SingleWebViewModel.class);
    }

    @Override
    protected void bindViewModel() {
        //这里必须要绑定设置viewModel否则xml中设置的viewModel不好使
        mDataBinding.setViewModel(mViewModel);
    }

    @Override
    protected void init() {
        this.settingConfig();
        this.setClient();
        //获取打开webView的 是否需要标题
        String webTitle = getIntent().getStringExtra("webTitle");
        //让viewModel去更新绑定在view中的title标题
        mViewModel.setSingleWebTitle(StringUtils.isEmpty(webTitle) ? "" : webTitle);
        //让viewModel去更新绑定在view中的title 去设置显示影藏
        mViewModel.setSingleWebTitleIsVisibility(!StringUtils.isEmpty(webTitle));

        //设置webView的Url
        String webUrl = getIntent().getStringExtra("webUrl");
        mDataBinding.jsBridgeView.loadUrl(webUrl);


        //设置webView返回监听
        mDataBinding.webReturnImage.setOnClickListener(view -> {
            finish();
        });
    }

    /**
     * 设置Js于Android原生交互
     */
    @Override
    protected void initListener() {
        mDataBinding.jsBridgeView.registerHandler("这里和jS规定好的方法名称", (data, function) -> {
            //data 是和js交互使用的 参数
            function.onCallBack(data);
        });
    }

    /**
     * 设置webView监听Client
     */
    private void setClient() {
        mDataBinding.jsBridgeView.setWebViewClient(new IBridgeWebViewClient(mDataBinding.jsBridgeView) {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
                return super.shouldOverrideUrlLoading(view, request);
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                super.onPageFinished(view, url);

            }

            @TargetApi(Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onReceivedError(WebView view, WebResourceRequest webResourceRequest, WebResourceError webResourceError) {
                super.onReceivedError(view, webResourceRequest, webResourceError);
                if (!NetworkUtils.isConnected()) {
                    view.loadUrl("about:blank");// 避免出现默认的错误界面
                    setErrorPage("403");// 加载自定义错误页面
                }
                if (webResourceRequest.isForMainFrame()) {//是否是为 main frame创建
                    view.loadUrl("about:blank");// 避免出现默认的错误界面
                    setErrorPage("连接超时");// 加载自定义错误页面
                }
            }

            @TargetApi(Build.VERSION_CODES.M)
            @Override
            public void onReceivedHttpError(WebView view, WebResourceRequest request, WebResourceResponse errorResponse) {
                super.onReceivedHttpError(view, request, errorResponse);
            }

            @Override
            public void onFormResubmission(WebView view, Message dontResend, Message resend) {
                super.onFormResubmission(view, dontResend, resend);
                resend.sendToTarget();
            }

        });

        mDataBinding.jsBridgeView.requestFocus();
        mDataBinding.jsBridgeView.setWebChromeClient(new WebChromeClient() {
            @Override
            public boolean onShowFileChooser(WebView webView, ValueCallback<Uri[]> filePathCallback, FileChooserParams fileChooserParams) {
                return true;
            }

            @Override
            public void onProgressChanged(WebView view, int newProgress) {
                super.onProgressChanged(view, newProgress);
                mDataBinding.webProgress.setProgress(newProgress);
                mDataBinding.webProgress.setVisibility(newProgress == 100 ? View.INVISIBLE : View.VISIBLE);
            }
        });
    }

    private final Handler handler = new Handler(Looper.getMainLooper());
    private boolean isError = false;

    /**
     * 设置加载错误页面
     * @param s 错误标识
     */
    private void setErrorPage(String s) {
        handler.postDelayed(() -> {
            isError = true;
            mDataBinding.jsBridgeView.clearHistory();
            mDataBinding.jsBridgeView.loadUrl(errorPage);
        }, 10);
    }

    /**
     * 设置配置webView
     */
    private void settingConfig() {
        mDataBinding.jsBridgeView.getSettings().setDomStorageEnabled(true);
        mDataBinding.jsBridgeView.setDefaultHandler(new DefaultHandler());
        mDataBinding.jsBridgeView.getSettings().setDisplayZoomControls(true);
        mDataBinding.jsBridgeView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        //打开缓存
        mDataBinding.jsBridgeView.getSettings().setDatabaseEnabled(true);
        // 开启
        mDataBinding.jsBridgeView.getSettings().setAppCacheEnabled(true);
        // 设置缓存模式，非常重要，决定了webview缓存资源的方式
        mDataBinding.jsBridgeView.getSettings().setCacheMode(WebSettings.LOAD_DEFAULT);
        mDataBinding.jsBridgeView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mDataBinding.jsBridgeView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        mDataBinding.jsBridgeView.getSettings().setBlockNetworkImage(false);//解决图片不显示
        //解决webview不能使用h5定位问题
        String dir = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath();
        mDataBinding.jsBridgeView.getSettings().setGeolocationDatabasePath(dir);
        mDataBinding.jsBridgeView.getSettings().setGeolocationEnabled(true);// 启用地理

        WebSettings webSettings = mDataBinding.jsBridgeView.getSettings();
        webSettings.setUseWideViewPort(true);
        webSettings.setLoadWithOverviewMode(true);
        webSettings.setDefaultTextEncodingName("UTF-8");
        webSettings.setAllowContentAccess(true); // 是否可访问Content Provider的资源，默认值 true
        webSettings.setAllowFileAccess(true);    // 是否可访问本地文件，默认值 true
        // 是否允许通过file url加载的Javascript读取本地文件，默认值 false
        webSettings.setAllowFileAccessFromFileURLs(true);
        // 是否允许通过file url加载的Javascript读取全部资源(包括文件,http,https)，默认值 false
        webSettings.setAllowUniversalAccessFromFileURLs(true);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
        webSettings.setBlockNetworkImage(false);//解决图片不显示
    }


    /**
     * 页面关闭回退拦截
     */
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        //判断是否加载错误了
        if (isError) {
            this.finish();
            return;
        }
        if (!isError) {
            //判断当前页面是否可以回退
            if (mDataBinding.jsBridgeView.canGoBack()) {
                mDataBinding.jsBridgeView.goBack();
                return;
            }
        }
        //如果都不存在最终关闭当前页面
        this.finish();
    }

    /*
     * 改变返回键的功能,当网页中有需要返回的界面时,网页中优先
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            mDataBinding.jsBridgeView.loadUrl("javascript:userAppGoback()");
            if (mDataBinding.jsBridgeView.canGoBack()) {
                mDataBinding.jsBridgeView.goBack();
                return true;
            }
        }
        return super.onKeyDown(keyCode, event);
    }
}
